<template>
    <div id="graph">
        <canvas ref="canvas" 
        @mousedown="startDragging" v-on:mousemove="dragging($event), drawLineToMouse($event)" @mouseup="stopDragging" 
        @click="isOnCircle"></canvas>   
    </div>
    <button @click="exportPDF">导出文件</button>
</template>
  
<script>
    import bus from '@/utils/bus';
    import html2canvas from 'html2canvas';
    import JsPDF from 'jspdf';
    import { ref, onMounted, watch } from 'vue';

    export default {
        name:'Graph',
        props: ['points', 'sides', 'allSorts'],
        setup(props) {
            const canvas = ref();
            let ctx = ref();
            let psp = [];
            const isDragging = ref(false);

            //鼠标事件相对于元素的偏移量
            const offsetX = ref(20);
            const offsetY = ref(20);

            function initContext() {
                // 设置canvas元素的宽度和高度为组件的宽度和高度
                canvas.value.width = canvas.value.offsetWidth;
                canvas.value.height = canvas.value.offsetHeight;

                ctx = canvas.value.getContext('2d');
            }

            function drawCircles() {

                props.points.forEach(point => {
                    // 绘制所有圆点
                    if(point.isactive === true) {
                        ctx.fillStyle = 'red'
                    }
                    else if(point.isactive === false) {
                        ctx.fillStyle = point.color;
                    }
                    ctx.strokeStyle = 'black';
                    ctx.beginPath();
                    ctx.arc(point.x, point.y, 8, 0, 2 * Math.PI);
                    ctx.closePath();
                    ctx.fill();
                    ctx.stroke(); 

                    //绘制所有圆点的名字
                    ctx.fillStyle = 'black';
                    ctx.font = '16px Arial';
                    ctx.fillText(`${point.title}`, point.x - 5 - point.title.length * 4, point.y - 12);
                });
            }

            function startDragging(event) {
                isDragging.value = true;
                offsetX.value = event.clientX;
                offsetY.value = event.clientY;
            }

            function dragging(event) {
                props.points.forEach((point) => {
                    if (isDragging.value && point.isactive == true) {
                        const rect = canvas.value.getBoundingClientRect();

                        //鼠标事件相对于canvas元素左上角的位置
                        const x = event.clientX - rect.left;
                        const y = event.clientY - rect.top;

                        point.x = x;
                        point.y = y;

                        // 清空画布
                        ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                        drawCircles();
                        drawSides();
                    }
                }) 
            }

            function stopDragging() {
                isDragging.value = false;
            }

            //判断点击位置是否在点上，是则激活点。绑定边的添加
            function isOnCircle(event) {
                const rect = canvas.value.getBoundingClientRect();
                let noactive = 0;
                let on = 0;

                //鼠标事件相对于canvas元素左上角的位置
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;

                // 计算鼠标点击位置与圆心的距离
                for(let i = 0; i < props.points.length; i++) {
                    let distance = Math.sqrt(Math.pow(x - props.points[i].x, 2) + Math.pow(y - props.points[i].y, 2));
                    if(distance < 8) {
                        on++;
                        if(on > 1) {
                            return
                        }
                        props.points[i].isactive = true;
                        const id = props.points[i].id;
                        bus.emit('checkpointactive', id);
                        // 清空画布
                        ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                        drawCircles();
                        drawSides();
                        if(psp.length === 0) {
                            psp.push(id);
                        }
                        else if(psp.length === 1 && psp[0] !== id) {
                            psp.push(id);
                            bus.emit('drawSide', psp);
                        }
                        else if(psp.length === 2 && psp[1] === id) {
                            psp.splice(0, psp.length);
                            psp.push(id);
                        }
                        else if(psp.length === 2 && psp[0] !== id && psp[1] !== id) {
                            psp[0] = psp[1];
                            psp[1] = id;
                            bus.emit('drawSide', psp);
                        }
                        else if(psp.length === 2 && psp[0] === id && psp[1] !== id) {
                            psp.splice(1,1);
                        }
                        else if(psp.length === 2 && psp[0] !== id && psp[1] === id) {
                            psp[0] = psp[1];
                            psp.splice(1,1);
                        }
                    }
                    else if(distance > 8) {
                        noactive++;
                        props.points[i].isactive = false;
                    }
                }
                if(noactive === props.points.length) {
                    psp.splice(0, psp.length);
                }
                // 清空画布
                ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                drawCircles();
                drawSides();
            }

            function drawLineToMouse(event) {
                const rect = canvas.value.getBoundingClientRect();

                //鼠标事件相对于canvas元素左上角的位置
                const x = event.clientX - rect.left;
                const y = event.clientY - rect.top;
                props.points.forEach((point) => {
                    if(point.isactive === true) {
                        // 清空画布
                        ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                        drawCircles();
                        drawSides();

                        // 绘制直线
                        ctx.beginPath();
                        ctx.moveTo(point.x, point.y);
                        ctx.lineTo(x, y);
                        ctx.stroke();
                        ctx.closePath();
                    }
                })
            }

            //绘制所有边
            function drawSides() {
                let sx;
                let ex;
                let sy;
                let ey;
                for(let i = 0; i < props.sides.length; i++) {
                    ctx.beginPath();
                    for(let j = 0; j < props.points.length; j++) {
                        const name1 = props.sides[i].title.slice(1, props.points[j].title.length + 1);
                        if(props.points[j].title === name1) {
                            ctx.moveTo(props.points[j].x, props.points[j].y);
                            sx = props.points[j].x;
                            sy = props.points[j].y;
                            break;
                        }
                    }
                    for(let k = 0; k < props.points.length; k++) {
                        const name2 = props.sides[i].title.slice(-props.points[k].title.length -1, -1);
                        if(props.points[k].title === name2) {
                            ctx.lineTo(props.points[k].x, props.points[k].y);
                            ex = props.points[k].x;
                            ey = props.points[k].y;
                            break;
                        }
                    }
                    // 绘制箭头
                    const angle = Math.atan2(ey - sy, ex - sx);
                    const arrowLength = 12;  // 箭头长度
                    ctx.moveTo((sx+ex)/2, (sy+ey)/2);
                    ctx.lineTo((sx+ex)/2 - arrowLength * Math.cos(angle - Math.PI / 6), (sy+ey)/2 - arrowLength * Math.sin(angle - Math.PI / 6));
                    ctx.moveTo((sx+ex)/2, (sy+ey)/2);
                    ctx.lineTo((sx+ex)/2 - arrowLength * Math.cos(angle + Math.PI / 6), (sy+ey)/2 - arrowLength * Math.sin(angle + Math.PI / 6));
                    ctx.stroke();
                    ctx.closePath();
                }
                
            }

            function exportPDF() {
	            const ele = document.getElementById('graph');
	            html2canvas(ele , {
	            dpi: 96, // 分辨率
	            scale: 1, // 设置缩放
	            useCORS: true, // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。,
	            bgcolor: '#ffffff', // 应该这样写
	            logging: false, // 打印日志用的 可以不加默认为false
	            }).then((canvas) => {
	                const contentWidth = canvas.width;
	                const contentHeight = canvas.height;
                    console.log(contentWidth, contentHeight)
                    // 一页pdf显示html页面生成的canvas高度;
                    const pageHeight = (contentWidth / 592.28) * 841.89;
                    // 未生成pdf的html页面高度
                    let leftHeight = contentHeight;
                    // 页面偏移
                    let position = 0;
                    // a4纸的尺寸[595.28,841.89]，html页面生成的canvas在pdf中图片的宽高
                    const imgWidth = 595.28;
                    const imgHeight = (595.28 / contentWidth) * contentHeight;
                    const startY = 600;
                    const startX = 10;
                    const cellWidth = 592.28;
                    const cellHeight = 10;
                    const pageData = canvas.toDataURL('image/jpeg', 1.0);
                    const pdf = new JsPDF('', 'pt', 'a4');
                    if (leftHeight < pageHeight) {
                        pdf.addFont('path/to/font.ttf', 'CustomFont', 'normal');
                        pdf.setFont('CustomFont');
                        pdf.setFontSize(18);
                        pdf.text('Topology Diagram and Topological Sorting Sequence of Group 7', 15, 30);
                        pdf.setFontSize(16);
                        pdf.text('Topology Diagram:', startX, 90);
                        pdf.addImage(pageData, 'JPEG', 0, 120, imgWidth, imgHeight);
                        pdf.text('Topological Sorting Sequence:', startX, 570);
                        pdf.setFontSize(8);
                        for (let i = 0; i < props.allSorts.length; i++) {
                            const text = props.allSorts[i].sequence;
                            const yPos = startY + (i + 1) * cellHeight;
                            pdf.text(text, startX, yPos + 10);
                        }
                    } 
                    else {
                        // 分页
                        while (leftHeight > 0) {
                            pdf.addImage(
                                pageData,
                                'JPEG',
                                0,
                                position,
                                imgWidth,
                                imgHeight
                            );
                            leftHeight -= pageHeight;
                            position -= 841.89;
                            // 避免添加空白页
                            if (leftHeight > 0) {
                                pdf.addPage();
                            }
                        }
                    }
                    // 可动态生成
                    pdf.save(`Topology Diagram and Topological Sorting Sequence of Group 7.pdf`);
	            });
            }

            watch(() => props.points, () => {
                // 清空画布
                ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                drawCircles();
                drawSides();
            }, {
                deep: true
            });

            watch(() => props.sides, () => {
                // 清空画布
                ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                drawCircles();
                drawSides();
            }, {
                deep: true
            });


            onMounted(() => {
                initContext();
                // 清空画布
                ctx.clearRect(0, 0, canvas.value.width, canvas.value.height);
                drawCircles();
                drawSides();
            });

            return {
                canvas,
                startDragging,
                dragging,
                stopDragging,
                isOnCircle,
                drawLineToMouse,
                exportPDF
            }
        }
    }
</script>
  
<style scoped>
#graph{
    width: 100%;
    height: 90%;
}
canvas {
    width: 100%;
    height: 90%;
    background: #eee;
    border: 1px solid black;
    position: absolute;
    right: 0;
    bottom: 0;
    overflow: auto;
}
button{
    width: 6rem;
    height: 2rem;
    margin-right: 1rem;
    color: #fff;
    background: linear-gradient(to right, #b6a19e, #6c648b);
    border: 1px solid #ddd;
    border-radius: .3125rem;
    cursor: pointer;
    position: absolute;
    left: 14rem;
    top: 1.225rem;
}
</style>